VimUnDo F<8,-QŽ:^ 8hk?k/;>GGGGhGe_hG5_GhGFJ|5_HhGG~5_hG function startUploadTile(file) {5_hG // Tile setup5_hG/ const tile = document.createElement('div');5_ hG tile.className = 'tile';5_ hG/ const icon = document.createElement('img');5_ hG icon.className = 'icon';5_ hG icon.src = icons.file;5_ hG/ const name = document.createElement('div');5_  hG name.className = 'filename';5_ hG! name.textContent = file.name;5_hG6 const progressbar = document.createElement('div');5_hG* progressbar.className = 'progressbar';5_hG3 const progress = document.createElement('div');5_hG$ progress.className = 'progress';5_hG progress.style.width = '0%';5_hG& progressbar.appendChild(progress);5_hG5_hG tile.appendChild(icon);5_hG tile.appendChild(name);5_hG" tile.appendChild(progressbar);5_hG grid.appendChild(tile);5_hG5_hG // Upload using WebSocket5_hG9 const ws = new WebSocket(`ws://${location.host}/ws`);5_hG" ws.binaryType = 'arraybuffer';5_hG let sent = 0;5_ hG5_! hG ws.onopen = async () => {5_ "!hGF ws.send(JSON.stringify({type: 'start', filename: file.name}));5_!#"hG" const chunkSize = 64*1024;5_"$#hG" while (sent < file.size) {5_#%$ hG= const chunk = file.slice(sent, sent + chunkSize);5_$&% hG/ ws.send(await chunk.arrayBuffer());5_%'& hG sent += chunkSize;5_&('hG }5_')(hGD ws.send(JSON.stringify({type: 'end', filename: file.name}));5_(*)hG };5_)+*hG5_*,+hG ws.onmessage = (event) => {5_+-,hG, const data = JSON.parse(event.data);5_,.-hG' if (data.type === 'progress') {5_-/. hGP const pct = Math.min(100, Math.round(100 * data.bytes / file.size));5_.0/ hG- progress.style.width = pct + '%';5_/10hG* } else if (data.type === 'done') {5_021 hG* progress.style.width = '100%';5_132 hG, tile.style.borderColor = '#0f0';5_243hG }5_354hG };5_465hG}5_576hG5_687hG5_7:8vhG( WebSocket File Upload 0 +
5_8;9:vhG  5_:<;!hG 7 5_;=< hG  / 5_<>= hG  6 5_=?> hG  7 5_>@?hG! ) 5_?A@hG$  5_@BA hGX 5_ACB hG[ =5_BDC hG\  5_CED hG^  5_DFEhG_5_EGFhG`) 5_FGhGd/ 5_8:9vhG  <( WebSocket File Upload 0 +
!DOCTYPE html>5_hG*( WebSocket File Upload